#include <cstring>
#include <iostream>
#include <typeinfo>

/*
模板的实参推演
*/
int sum(int a, int b) {
    return a + b;
}
class Foo {
public:
    int sum(int a, int b) {
        return a + b;
    }
};

template <typename T>
void func(T a) {
    std::cout << typeid(a).name() << std::endl;
}

template <typename R, typename A1, typename A2>
void func2(R (*a)(A1, A2)) {
    std::cout << typeid(R).name() << std::endl;
    std::cout << typeid(A1).name() << std::endl;
    std::cout << typeid(A2).name() << std::endl;
}

template <typename R, typename T, typename A1, typename A2>
void func3(R (T::*a)(A1, A2)) {
    std::cout << typeid(R).name() << std::endl;
    std::cout << typeid(T).name() << std::endl;
    std::cout << typeid(A1).name() << std::endl;
    std::cout << typeid(A2).name() << std::endl;
}
int main() {
    func(10);
    func("abc");
    func(sum);
    func(&Foo::sum);

    std::cout << "------------------------" << std::endl;
    func2(sum);

    std::cout << "------------------------" << std::endl;
    func3(&Foo::sum);
    return 0;
}

#if 0
/*
模板的完全特例化 和 部分特例化
*/
template <typename T>
bool compare(T a, T b) {
    std::cout << "call compare<T>(T,T)" << std::endl;
    return a > b;
}

// 模板 完全特例化
template <>
bool compare<const char*>(const char* a, const char* b) {
    std::cout << "call compare<const char*>(const char*,const char*)"
              << std::endl;
    return strcmp(a, b) > 0;
}

//===============================================================
int sum(int a, int b) {
    return a + b;
}
// 类模板
template <typename T>
class Vector {
public:
    Vector() {
        std::cout << "call Vector template init" << std::endl;
    }
};
// 针对char*类型提供的完全特例化版本
template <>
class Vector<char*> {
public:
    Vector() {
        std::cout << "call Vector<char*> init" << std::endl;
    }
};
// 针对指针类型提供的部分特例化版本
template <typename Ty>
class Vector<Ty*> {
public:
    Vector() {
        std::cout << "call Vector<Ty*> init" << std::endl;
    }
};
// 对函数指针中各个部分的类型拆开处理
template <typename R, typename A1, typename A2>
class Vector<R (*)(A1, A2)> {
public:
    Vector() {
        std::cout << "call Vector<R (*)(A1, A2)> init" << std::endl;
    }
};
// 对函数类型部分特例化
template <typename R, typename A1, typename A2>
class Vector<R(A1, A2)> {
public:
    Vector() {
        std::cout << "call Vector<R (A1, A2)> init" << std::endl;
    }
};
int main() {
    std::cout << compare(1, 2) << std::endl;
    std::cout << compare("ab", "bc") << std::endl;
    std::cout << "====================" << std::endl;

    Vector<int> v1;    // 编译器实例化一个模板类
    Vector<char*> v2;  // 使用完全特例化版本
    Vector<int*> v3;   // 使用部分特例化版本
    // int (*)(int, int)为函数指针，该指针指向一个
    // 接收两个int作为形参返回值为int类型的函数，使用部分特例化版本
    Vector<int (*)(int, int)> v4;
    Vector<int(int, int)> v5;
    std::cout << "====================" << std::endl;

    // 区分函数指针 和 函数类型
    typedef int (*PFUNC)(int, int);
    PFUNC pfun1 = sum;
    std::cout << pfun1(10, 20) << std::endl;

    typedef int PFUNC2(int, int);
    PFUNC2* pfun2 = sum;
    std::cout << (*pfun2)(20, 30) << std::endl;
    return 0;
}
#endif
